text: Add API to compute cursor extents
authorFlorian Müllner <fmuellner@gnome.org>
Tue, 6 Jul 2021 20:39:05 +0000 (22:39 +0200)
committerFlorian Müllner <fmuellner@gnome.org>
Wed, 7 Jul 2021 17:33:12 +0000 (19:33 +0200)
The extents that correspond to the strong/weak cursor at a given
character position can be used for example to point a popover to
text in the widget.

gtk/gtktext.c
gtk/gtktext.h

index f3c23c3365dc06854349149b3755bc1bfbdbc78a..8e7fbf3cc1f3e5b3f123aafcc731f8a80bd02779 100644 (file)
@@ -7117,6 +7117,69 @@ gtk_text_get_truncate_multiline (GtkText *self)
   return priv->truncate_multiline;
 }
 
+/**
+ * gtk_text_compute_cursor_extents:
+ * @self: a `GtkText`
+ * @position: the character position
+ * @strong: (out) (optional): location to store the strong cursor position
+ * @weak: (out) (optional): location to store the weak cursor position
+ *
+ * Determine the positions of the strong and weak cursors if the
+ * insertion point in the layout is at @position.
+ *
+ * The position of each cursor is stored as a zero-width rectangle.
+ * The strong cursor location is the location where characters of
+ * the directionality equal to the base direction are inserted.
+ * The weak cursor location is the location where characters of
+ * the directionality opposite to the base direction are inserted.
+ *
+ * The rectangle positions are in widget coordinates.
+ *
+ * Since: 4.4
+ */
+void
+gtk_text_compute_cursor_extents (GtkText         *self,
+                                 gsize            position,
+                                 graphene_rect_t *strong,
+                                 graphene_rect_t *weak)
+{
+  PangoLayout *layout;
+  PangoRectangle pango_strong_pos;
+  PangoRectangle pango_weak_pos;
+  int offset_x, offset_y, index;
+  const char *text;
+
+  g_return_if_fail (GTK_IS_TEXT (self));
+
+  layout = gtk_text_ensure_layout (self, TRUE);
+  text = pango_layout_get_text (layout);
+  position = CLAMP (position, 0, g_utf8_strlen (text, -1));
+  index = g_utf8_offset_to_pointer (text, position) - text;
+
+  pango_layout_get_cursor_pos (layout, index,
+                               strong ? &pango_strong_pos : NULL,
+                               weak ? &pango_weak_pos : NULL);
+  gtk_text_get_layout_offsets (self, &offset_x, &offset_y);
+
+  if (strong)
+    {
+      graphene_rect_init (strong,
+                          offset_x + pango_strong_pos.x / PANGO_SCALE,
+                          offset_y + pango_strong_pos.y / PANGO_SCALE,
+                          0,
+                          pango_strong_pos.height / PANGO_SCALE);
+    }
+
+  if (weak)
+    {
+      graphene_rect_init (weak,
+                          offset_x + pango_weak_pos.x / PANGO_SCALE,
+                          offset_y + pango_weak_pos.y / PANGO_SCALE,
+                          0,
+                          pango_weak_pos.height / PANGO_SCALE);
+    }
+}
+
 static void
 gtk_text_real_undo (GtkWidget  *widget,
                     const char *action_name,
index 38ae25c42117f6469b56f6f5d737b9844fb2ad87..4240aa92f5128462363ab7b0cfd5ddf4fac342a5 100644 (file)
@@ -159,6 +159,11 @@ void            gtk_text_set_truncate_multiline         (GtkText         *self,
 GDK_AVAILABLE_IN_ALL
 gboolean        gtk_text_get_truncate_multiline         (GtkText         *self);
 
+GDK_AVAILABLE_IN_4_4
+void            gtk_text_compute_cursor_extents         (GtkText         *self,
+                                                         gsize            position,
+                                                         graphene_rect_t *strong,
+                                                         graphene_rect_t *weak);
 
 
 G_END_DECLS